package com.recycle.system.service.impl;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.recycle.common.core.domain.entity.SysUser;
import com.recycle.common.enums.Recyclable;
import com.recycle.common.utils.DateUtils;
import com.recycle.common.utils.SecurityUtils;
import com.recycle.common.utils.StringUtils;
import com.recycle.system.domain.Order;
import com.recycle.system.domain.OrderItem;
import com.recycle.system.domain.WasteResource;
import com.recycle.system.domain.dto.PayChartData;
import com.recycle.system.domain.dto.Payment;
import com.recycle.system.domain.dto.SummaryOrderItem;
import com.recycle.system.domain.vo.CommunityChart;
import com.recycle.system.domain.vo.PayChart;
import com.recycle.system.domain.vo.PreviewDetail;
import com.recycle.system.mapper.*;
import com.recycle.system.service.IOrderItemService;
import com.recycle.system.service.IOrderService;
import com.recycle.system.service.IWasteResourceService;
import javafx.util.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.recycle.system.domain.OrderDetail;
import com.recycle.system.service.IOrderDetailService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 订单信息详情Service业务层处理
 *
 * @author recycle
 * @date 2023-03-11
 */
@Service
public class OrderDetailServiceImpl implements IOrderDetailService {
    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private IOrderService orderService;

    @Resource
    private IWasteResourceService resourceService;

    @Resource
    private IOrderItemService itemService;

    @Resource
    private WasteResourceTypeMapper resourceTypeMapper;


    @Resource
    private WasteResourceMapper wasteResourceMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private OrderItemMapper orderItemMapper;


    /**
     * 查询订单信息详情
     *
     * @param orderDetailId 订单信息详情主键
     * @return 订单信息详情
     */
    @Override
    public OrderDetail selectOrderDetailByOrderDetailId(Long orderDetailId) {
        return orderDetailMapper.selectOrderDetailByOrderDetailId(orderDetailId);
    }

    /**
     * 查询订单信息详情列表
     *
     * @param orderDetail 订单信息详情
     * @return 订单信息详情
     */
    @Override
    public List<OrderDetail> selectOrderDetailList(OrderDetail orderDetail) {
        return orderDetailMapper.selectOrderDetailList(orderDetail);
    }

    /**
     * 查询订单信息详情列表
     *
     * @param orderDetail 订单信息详情
     * @return 订单信息详情集合
     */
    @Override
    public List<OrderDetail> fuzzySelectOrderDetailList(OrderDetail orderDetail) {
        QueryWrapper wrapper = new QueryWrapper<OrderDetail>();

        Stream<Field> stream = Arrays.stream(OrderDetail.class.getDeclaredFields());
        stream.forEach(field -> {
            field.setAccessible(true);
            if (field.getType() != String.class) {
                return;
            }
            try {
                String value = (String) field.get(orderDetail);
                if (StringUtils.isNotEmpty(value)) {
                    wrapper.like(field.getName(), value);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        return orderDetailMapper.selectList(wrapper);
    }

    /**
     * 新增订单信息详情
     *
     * @param orderDetail 订单信息详情
     * @return 结果
     */
    @Override
    public int insertOrderDetail(OrderDetail orderDetail) {
        orderDetail.setCreateTime(DateUtils.getNowDate());
        return orderDetailMapper.insertOrderDetail(orderDetail);
    }

    /**
     * 修改订单信息详情
     *
     * @param orderDetail 订单信息详情
     * @return 结果
     */
    @Override
    public int updateOrderDetail(OrderDetail orderDetail) {
        orderDetail.setUpdateTime(DateUtils.getNowDate());
        return orderDetailMapper.updateOrderDetail(orderDetail);
    }

    /**
     * 批量删除订单信息详情
     *
     * @param orderDetailIds 需要删除的订单信息详情主键
     * @return 结果
     */
    @Override
    public int deleteOrderDetailByOrderDetailIds(Long[] orderDetailIds) {
        return orderDetailMapper.deleteOrderDetailByOrderDetailIds(orderDetailIds);
    }

    /**
     * 删除订单信息详情信息
     *
     * @param orderDetailId 订单信息详情主键
     * @return 结果
     */
    @Override
    public int deleteOrderDetailByOrderDetailId(Long orderDetailId) {
        return orderDetailMapper.deleteOrderDetailByOrderDetailId(orderDetailId);
    }

    /**
     * 查看支付预览
     *
     * @param orderDetail@return 结果
     */
    @Override
    public List<PreviewDetail> preview(OrderDetail orderDetail) {

        List<OrderItem> orderItems = orderService.selectRelativeResource(orderDetail.getOrderId());

        List<PreviewDetail> previews = new ArrayList<>();

        orderItems.stream().filter(item -> {
            return Recyclable.valuesList().contains(item.getResourceTypeId());
        }).forEach(item -> {
            BigDecimal preIncome = resourceTypeMapper.selectPriceByResourceTypeId(item.getResourceTypeId());

            previews.add(PreviewDetail.builder()
                    .resourceTypeId(item.getResourceTypeId())
                    .resourceType(item.getResourceType())
                    .preIncome(preIncome.multiply(item.getWeight()))
                    .actualIncome(item.getPrice().multiply(item.getWeight()))
                    .weight(item.getWeight())
                    .packageReiurement(item.getPackageRequirement())
                    .percentage(item.getPrice().divide(preIncome, 2))
                    .build()
            );
        });
        BigDecimal totalActualIncome = previews.stream().map(PreviewDetail::getActualIncome).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalPreIncome = previews.stream().map(PreviewDetail::getPreIncome).reduce(BigDecimal.ZERO, BigDecimal::add);
        previews.add(PreviewDetail.builder()
                .preIncome(totalPreIncome)
                .actualIncome(totalActualIncome)
                .resourceType("总览")
                .percentage(totalActualIncome.divide(totalPreIncome, 2))
                .build());

        return previews;
    }

    /**
     * 完成支付
     *
     * @param payment@return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int complete(Payment payment) {


        //先把总览去掉

        PreviewDetail overview = payment.getPreviewDetail().get(payment.getPreviewDetail().size() - 1);
        payment.getPreviewDetail().remove(payment.getPreviewDetail().size() - 1);

        //首先，完成资源的转移
        long orderId = payment.getOrderId();


        List<PreviewDetail> previewDetails = payment.getPreviewDetail();
        long residentId = wasteResourceMapper.selectPublisherIdByOrderId(orderId);

        QueryWrapper residentWrapper = new QueryWrapper<WasteResource>();
        residentWrapper.eq("owner_id", residentId);
        List<WasteResource> residentResources = wasteResourceMapper.selectList(residentWrapper);
        Map<Long, BigDecimal> previewContains = previewDetails.stream()
                .collect(Collectors.toMap(
                        PreviewDetail::getResourceTypeId,
                        PreviewDetail::getWeight
                ));
        //对居民的资源进行重量更新，刚好交易完的就删除
        residentResources.stream().forEach(item -> {
            if (previewContains.containsKey(item.getResourceTypeId())) {
                BigDecimal subtract = item.getWeight().subtract(previewContains.get(item.getResourceTypeId()));
                if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                    item.setWeight(subtract);
                    updateResourceData(item);
                } else if (subtract.compareTo(BigDecimal.ZERO) == 0) {
                    item.setWeight(BigDecimal.ZERO);
                    updateResourceData(item);
                } else {
                    throw new RuntimeException("交易失败！居民的" + item.getResourceType() + "类型资源重量不足！");
                }
            }
        });

        QueryWrapper merchantWrapper = new QueryWrapper<WasteResource>();
        long merchantId = wasteResourceMapper.selectFinisherIdByOrderId(orderId);
        merchantWrapper.eq("owner_id", merchantId);
        List<WasteResource> merchantResources = wasteResourceMapper.selectList(merchantWrapper);

        //如果此时商家没有任何资源，直接新增
        if (merchantResources.isEmpty()) {
            previewContains.forEach((key, value) -> {
                WasteResource resource = WasteResource.builder()
                        .resourceTypeId(key)
                        .resourceType(Recyclable.findLabel(key))
                        .ownerId(SecurityUtils.getUserId())
                        .weight(value)
                        .build();
                resourceService.insertWasteResource(resource);
            });
        } else {
            //对商家的资源进行重量更新，没有的就新增
            previewContains.forEach((key, value) -> {
                if (!merchantResources.stream().anyMatch(item -> item.getResourceTypeId().equals(key))) {
                    WasteResource resource = WasteResource.builder()
                            .resourceTypeId(key)
                            .resourceType(Recyclable.findLabel(key))
                            .ownerId(SecurityUtils.getUserId())
                            .weight(value)
                            .build();
                    resourceService.insertWasteResource(resource);
                } else {
                    WasteResource resource = merchantResources.stream().filter(item -> item.getResourceTypeId().equals(key)).findFirst().get();
                    resource.setWeight(resource.getWeight().add(value));
                    updateResourceData(resource);
                }
            });
        }

        //资源转移完成后，更新订单的状态
        orderMapper.updateOrderStatus(orderId, 1L);

        //完成用户余额的交易
        BigDecimal merchantBalance = sysUserMapper.selectBalance(SecurityUtils.getUserId());
        if (merchantBalance.subtract(overview.getActualIncome()).compareTo(BigDecimal.ZERO) >= 0) {
            sysUserMapper.updateBalance(merchantBalance.subtract(overview.getActualIncome()), SecurityUtils.getUserId());

            sysUserMapper.updateBalance(sysUserMapper.selectBalance(residentId).add(overview.getActualIncome()), residentId);
        } else {
            throw new RuntimeException("商家余额不足，不能完成支付！");
        }
        //生成订单详情表
        OrderDetail orderDetail = OrderDetail.builder()
                .orderId(orderId)
                .preIncome(overview.getPreIncome())
                .actualIncome(overview.getActualIncome())
                .percentage(overview.getPercentage())
                .recycler(payment.getOrderDetail().getRecycler())
                .recyclerContact(payment.getOrderDetail().getRecyclerContact())
                .endTime(payment.getOrderDetail().getEndTime())
                .build();

        return orderDetailMapper.insertOrderDetail(orderDetail);
    }


    public int updateResourceData(WasteResource resource) {
        if (resource.getWeight().compareTo(BigDecimal.ZERO) > 0) {
            return wasteResourceMapper.updateById(resource);
        } else {
            return wasteResourceMapper.deleteWasteResourceByResourceId(resource.getResourceId());
        }
    }

    /**
     * 获取交易数据
     *
     * @return 结果
     */
    @Override
    public PayChart getPaymentData() {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        long userId = SecurityUtils.getUserId();
        wrapper.eq("status", 1).eq("publisher_id", userId).or().eq("finisher_id", userId);
        //获取用户已完成的所有订单
        List<Order> orders = orderMapper.selectList(wrapper);
        List<Long> collect = orders.stream().map(item -> item.getOrderId()).collect(Collectors.toList());
        if (collect.size() == 0) {
            return null;
        }
        QueryWrapper<OrderDetail> wrapper2 = new QueryWrapper<>();
        wrapper2.in("order_id", collect);
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(wrapper2);

        PayChart payChart = new PayChart();
        payChart.initListData();

        //设置数据
        List<String> collectDate = orderDetails.stream().map(item -> {
            return new SimpleDateFormat("yyyy-MM-dd").format(item.getCreateTime());
        }).collect(Collectors.toList());
        payChart.setListDate(collectDate);

        List<BigDecimal> collect1 = orderDetails.stream().map(item -> item.getPreIncome()).collect(Collectors.toList());
        payChart.getListData().get(0).setData(collect1);

        List<BigDecimal> collect2 = orderDetails.stream().map(item -> item.getActualIncome()).collect(Collectors.toList());
        payChart.getListData().get(1).setData(collect2);

        List<BigDecimal> collect3 = orderDetails.stream().map(item -> item.getPercentage().multiply(new BigDecimal("100"))).collect(Collectors.toList());
        payChart.getListData().get(2).setData(collect3);

        return payChart;
    }

    /**
     * 获取社区交易数据
     *
     * @return 结果
     */
    @Override
    public CommunityChart getCommunityPaymentData(Long deptId) {

        deptId = deptId == null ? SecurityUtils.getLoginUser().getDeptId() : deptId;
        SysUser temp = new SysUser();
        temp.setDeptId(deptId);
        List<SysUser> users = sysUserMapper.selectUserList(temp);


        //遍历所有用户，依次取出完成的订单数据，并存进列表
        Set<Long> allCompletedOrderIds = new HashSet<>();
        users.forEach(user -> {
            QueryWrapper<Order> orderWrapper = new QueryWrapper<>();
            orderWrapper.eq("status", 1).eq("publisher_id", user.getUserId()).or().eq("finisher_id", user.getUserId());
            List<Order> completedOrders = orderMapper.selectList(orderWrapper);
            List<Long> completedOrderIds = completedOrders.stream().map(Order::getOrderId).collect(Collectors.toList());
            allCompletedOrderIds.addAll(completedOrderIds);
        });
        List<Long> allCompletedOrders = new ArrayList<>(allCompletedOrderIds);
        if (allCompletedOrders.size() == 0) {
            return null;
        }
        List<SummaryOrderItem> summary = orderItemMapper.querySummaryOrderItem(allCompletedOrders);
        CommunityChart res = transformItem(summary);
        return res;
    }

    public CommunityChart transformItem(List<SummaryOrderItem> list) {
        CommunityChart communityChart = new CommunityChart();
        Map<String, Map<Long, BigDecimal>> groupedItems = new HashMap<>();

        // Group items by month and resource type
        for (SummaryOrderItem item : list) {
            String month = item.getMonth();
            Long resourceTypeId = item.getResourceTypeId();
            BigDecimal totalWeight = item.getTotalWeight();

            if (!groupedItems.containsKey(month)) {
                groupedItems.put(month, new HashMap<>());
            }

            Map<Long, BigDecimal> resourceTypeMap = groupedItems.get(month);
            if (!resourceTypeMap.containsKey(resourceTypeId)) {
                resourceTypeMap.put(resourceTypeId, BigDecimal.ZERO);
            }

            BigDecimal currentWeight = resourceTypeMap.get(resourceTypeId);
            resourceTypeMap.put(resourceTypeId, currentWeight.add(totalWeight));
        }

        // Convert grouped items to CommunityChart lists
        for (String month : groupedItems.keySet()) {
            communityChart.getDates().add(month);
            Map<Long, BigDecimal> resourceTypeMap = groupedItems.get(month);

            communityChart.getPaper().add(resourceTypeMap.getOrDefault(Recyclable.PAPER.getValue(), BigDecimal.ZERO));
            communityChart.getPlastic().add(resourceTypeMap.getOrDefault(Recyclable.PLASTIC.getValue(), BigDecimal.ZERO));
            communityChart.getMetal().add(resourceTypeMap.getOrDefault(Recyclable.METAL.getValue(), BigDecimal.ZERO));
            communityChart.getGlass().add(resourceTypeMap.getOrDefault(Recyclable.GLASS.getValue(), BigDecimal.ZERO));
            communityChart.getCloth().add(resourceTypeMap.getOrDefault(Recyclable.CLOTH.getValue(), BigDecimal.ZERO));

            BigDecimal totalWeight = BigDecimal.ZERO;
            for (BigDecimal weight : resourceTypeMap.values()) {
                totalWeight = totalWeight.add(weight);
            }
            communityChart.getTotalWeight().add(totalWeight);
        }

        // Calculate growth rate
        for (int i = 1; i < communityChart.getTotalWeight().size(); i++) {
            BigDecimal currentWeight = communityChart.getTotalWeight().get(i);
            BigDecimal previousWeight = communityChart.getTotalWeight().get(i - 1);
            BigDecimal growthRate = currentWeight.subtract(previousWeight).divide(previousWeight, 2, RoundingMode.HALF_UP);
            communityChart.getGrowthRate().add(growthRate);
        }

        return communityChart;
    }

//    /**
//     * 查看支付预览
//     *
//     * @param orderDetail@return 结果
//     */
//    @Override
//    public List<PreviewDetail> preview(OrderDetail orderDetail) {
//        //申请包含的resource
//        List<OrderItem> orderResources = itemService.selectOrderItemList(OrderItem.builder().orderId(orderDetail.getOrderId()).build());
//
//        //账号包含的resource
//        List<WasteResource> ownResources = resourceService.selectWasteResourceList(WasteResource.builder().ownerId(SecurityUtils.getUserId()).build());
//
//        List<PreviewDetail> previewDetails = new ArrayList<>();
//
//        List<Long> orderCollect = orderResources.stream().map(item -> {
//            return item.getResourceTypeId();
//        }).collect(Collectors.toList());
//        List<Long> ownCollect = ownResources.stream().map(item -> {
//            return item.getResourceTypeId();
//        }).collect(Collectors.toList());
//        //如果用户拥有的资源包含订单所含资源，则视为可以预览（除非重量不够）
//        if(ownCollect.containsAll(orderCollect)){
//
//            orderResources.forEach(item -> {
//                PreviewDetail detail = new PreviewDetail();
//                detail.setResourceTypeId(item.getResourceTypeId());
//                detail.setResourceType(item.getResourceType());
//                detail.setActualIncome(item.getPrice().multiply(item.getWeight()));
//                detail.setWeight(item.getWeight());
//                previewDetails.add(detail);
//            });
//            ownResources.forEach(item -> {
//                previewDetails.stream()
//                        .filter(order -> item.getResourceTypeId().equals(order.getResourceTypeId()) && item.getWeight().compareTo(order.getWeight()) > -1)
//                        .findFirst()
//                        .ifPresent(order -> {
//                            order.setPreIncome(item.getPrice().multiply(item.getWeight()));
//                            order.setPercentage(order.getActualIncome().divide(order.getPreIncome(), 2, BigDecimal.ROUND_HALF_UP));
//                        });
//            });
//            return previewDetails;
//        }else{
//            throw new RuntimeException("申请中包含自己未拥有的资源！");
//        }
//
//    }

}
